package com.yitiao.base.delay;

import cn.hutool.core.date.DateUtil;

import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

class TimeWheel {
    private int wheelSize;  // 大小
    private long tickMs;  // tick 滴答
    private int currentPos;  // 当前刻度
    private AtomicLong timestamp;
    private ConcurrentLinkedQueue<DelayedTask>[] buckets; // 槽位

    public TimeWheel(int wheelSize, long tickMs) {
        this.wheelSize = wheelSize;
        this.tickMs = tickMs;
        this.currentPos = 0;
        this.timestamp = new AtomicLong(System.currentTimeMillis());
        this.buckets = new ConcurrentLinkedQueue[wheelSize];
        // 为没一个槽位初始化一个队列容器，存储延迟任务
        for (int i = 0; i < wheelSize; i++) {
            buckets[i] = new ConcurrentLinkedQueue<>();
        }
        // 时间轮开始转动 -- 定时任务
        start();
    }

    public void addTask(DelayedTask task) {
        long expiration = task.getDelayTime() / tickMs;
        int pos = (int) ((currentPos + expiration) % wheelSize);
        buckets[pos].offer(task);
    }

    private void start() {
        // 根据 tick 循环执行
        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
        executor.scheduleAtFixedRate(() -> {
            long currentTime = System.currentTimeMillis();
            System.out.println(DateUtil.formatDateTime(new Date(currentTime)));
            currentPos = (int) ((currentTime - timestamp.get()) / tickMs % wheelSize);
            ConcurrentLinkedQueue<DelayedTask> bucket = buckets[currentPos];
            System.out.println(currentPos);
            while (!bucket.isEmpty()) {
                DelayedTask task = bucket.poll();
                if (task != null) {
                    task.run();
                }
            }
//            }
        }, 0, tickMs, TimeUnit.MILLISECONDS);
    }
}
